package com.yunwaikeji.gy_tool_library.task;

import android.os.AsyncTask;
import android.util.Log;

import com.yunwaikeji.gy_tool_library.utils.GYRandomUtils;
import com.yunwaikeji.gy_tool_library.utils.GYUiUtils;
import com.yunwaikeji.gy_tool_library.utils.GYUtils;

public abstract class GYAsyncTask<Task extends GYAsyncTask<?, ?, ?, ?>, Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
    private final Task task;
    private Integer tagId;//标记id
    private boolean canceled;//是否取消
    //    private boolean reStart;//是否重新开始
    private boolean starting;//线程是否已经开始
    private GYTaskListener taskListener;
    private boolean requestMainThread = false;//请求是否在主线程运行
    private boolean responseMainThread = true;//回调是否在主线程运行

    public GYAsyncTask() {
        task = (Task) this;
        while (GYUtils.isNullOrEmpty(tagId) || GYTaskManager.getInstance().has(tagId)) {
            tagId = GYRandomUtils.getRandom(1, 999999999);
        }
        GYTaskManager.getInstance().add(this);
    }

    public Integer getTagId() {
        return tagId;
    }

    public Task setCanceled(boolean canceled) {
        this.canceled = canceled;
        cancel(true);
        return task;
    }

    public boolean isCanceled() {
        return canceled;
    }

    public boolean isStarting() {
        return starting;
    }

    public Task setTaskListener(GYTaskListener taskListener) {
        this.taskListener = taskListener;
        return task;
    }

    public Task getTask() {
        return task;
    }

    // 方法1：onPreExecute（）
    // 作用：执行 线程任务前的操作
    // 注：根据需求复写
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        starting = true;
        if (taskListener != null) {
            taskListener.start();
        }
        if (requestMainThread) {
            doInBackground();
        }
    }

    // 方法2：doInBackground（）
    // 作用：接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
    // 注：必须复写，从而自定义线程任务
    @Override
    protected Result doInBackground(Params... params) {
        if (!requestMainThread) {
            doInBackground();
        }
        return null;
    }

    protected abstract Result doInBackground();

    // 方法3：onProgressUpdate（）
    // 作用：在主线程 显示线程任务执行的进度
    // 注：根据需求复写
    @Override
    protected void onProgressUpdate(Progress... values) {
        super.onProgressUpdate(values);
    }

    // 方法4：onPostExecute（）
    // 作用：接收线程任务执行结果、将执行结果显示到UI组件
    // 注：必须复写，从而自定义UI操作
    @Override
    protected void onPostExecute(Result result) {
        super.onPostExecute(result);
        if (taskListener != null) {
            taskListener.finish();
        }
        starting = false;
    }

    // 方法5：onCancelled()
    // 作用：将异步任务设置为：取消状态
    @Override
    protected void onCancelled() {
        super.onCancelled();
        if (taskListener != null) {
            taskListener.finish();
        }
    }

    public Task setRequestMainThread(boolean requestMainThread) {
        this.requestMainThread = requestMainThread;
        return task;
    }

    public boolean isRequestMainThread() {
        return requestMainThread;
    }

    public Task setResponseMainThread(boolean responseMainThread) {
        this.responseMainThread = responseMainThread;
        return task;
    }

    public boolean isResponseMainThread() {
        return responseMainThread;
    }

    public Integer start() {
        execute();
        return tagId;
    }

    public void stop() {
        if (taskListener != null) {
            taskListener.stop();
        }
        cancel(true);
    }

    public abstract void onLoading(long nowBytes, long totalBytes, long secondBytes);

    public abstract void onSuccess(Object response);

    public void onError(String error) {
        Log.e(getClass().getSimpleName(), error);
        if (taskListener != null) {
            if (responseMainThread) {
                GYUiUtils.runOnUiThread(() -> taskListener.error(error));
            } else {
                taskListener.error(error);
            }
        }
    }

    public void mainThread(Runnable runnable) {
        GYUiUtils.runOnUiThread(runnable);
    }
}
